package dp05.leertaak1.server;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import dp05.leertaak1.command.definitions.Command;
import dp05.leertaak1.command.definitions.RevertableCommand;
import dp05.leertaak1.command.implementations.Get;
import dp05.leertaak1.command.implementations.Update;
import dp05.leertaak1.dao.definitions.DAO;
import dp05.leertaak1.dao.implementations.*;
import dp05.leertaak1.server.protocol.ProtocolDbAvailable;

public class Server
{
    private static ArrayList<ClientHandler> clients = new ArrayList<ClientHandler>();
    public static Queue<RevertableCommand> actionQueue = new LinkedList<RevertableCommand>();
    public static DAO dao;

    public Server()
    {
        ClientListener listener = new ClientListener();
        new Thread(listener).start();
        dao = CsvDAO.getInstance();
    }

    public static void addClient(ClientHandler client)
    {
        clients.add(client);
    }

    public static void removeClient(ClientHandler client)
    {
        clients.remove(client);
        processQueueIfDbIsAvailable();
    }

    private static void processQueueIfDbIsAvailable()
    {
        boolean dbAvailable = true;
        for (ClientHandler client : clients)
        {
            if (client.getProtocol() instanceof ProtocolDbAvailable)
            {
                dbAvailable = false;
            }
        }
        if (dbAvailable)
        {
            Command get = new Get(dao);
            get.execute();
            
            RevertableCommand com;
            while((com = actionQueue.poll()) != null)
            {
                com.execute();
            }

            Command updateDb = new Update(dao);
            updateDb.execute();
            dao.cleanUp();
        }
    }

    public static void addCommandToQueue(RevertableCommand command)
    {
        actionQueue.add(command);
    }

    public static boolean isDatabaseAvailable()
    {
        for (ClientHandler client : clients)
        {
            if (client.getProtocol() instanceof ProtocolDbAvailable)
            {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args)
    {
        new Server();
    }
}